from datetime import datetime, time

from pandas import Series
from lq_client import client as lq
from .base_fucker import BaseFucker
from gateway.base_gateway import BaseGateway
from event import Event

from .base_fucker import FuckerStatus

import logging
logger = logging.getLogger('fucker')


class YzFucker(BaseFucker):
    def __init__(self, gateway: BaseGateway):
        super().__init__(gateway)
        self.MAX_ORDER_VOL = 168

    def on_tick(self, e: Event):
        tick = e.data

        if self.status != FuckerStatus.RUNNING:
            return

        vt_symbol = tick.vt_symbol

        # logger.debug(f'tick {tick.vt_symbol} {tick.datetime} finished: {self.finished[vt_symbol]}')

        if self.finished[vt_symbol]:
            return

        if self.change_pos[vt_symbol] < 0:
            if 1e10 > tick.ask_price_1 > 0:
                price = tick.bid_price_1
            else:
                return
                # price = tick.asks[0][0]
        else:
            if 1e10 > tick.bid_price_1 > 0:
                price = tick.ask_price_1
            else:
                return
        self.check_cancel_orders(vt_symbol, price)
        target_pos = self.target_pos.get(vt_symbol, 0)
        current_pos = self.position_management.get_position_holding(vt_symbol).current_pos

        if target_pos * current_pos <= -1:
            target_pos = 0

        pos_dif = target_pos - current_pos

        trading_pos = self.position_management.get_position_holding(vt_symbol).trading_pos
        logger.debug(f'symbol: {vt_symbol}, target: {target_pos}, current: {current_pos}, trading: {trading_pos}')

        if pos_dif == 0:
            if trading_pos != 0:
                logger.warning('target == current but trading != 0')
            return

        to_trade = pos_dif - trading_pos
        if (self.change_pos[vt_symbol] < 0 and to_trade < 0) or (self.change_pos[vt_symbol] > 0 and to_trade > 0):

            to_trade = self.max_order_vol_cons(to_trade)
            self.send_net_pos_order(vt_symbol, price, to_trade)

    def max_order_vol_cons(self, vol):
        if vol > self.MAX_ORDER_VOL:
            vol = self.MAX_ORDER_VOL
        elif vol < - self.MAX_ORDER_VOL:
            vol = - self.MAX_ORDER_VOL
        return vol

    def check_cancel_orders(self, vt_symbol, price):
        for order in self.position_management.get_position_holding(vt_symbol).active_orders.values():
            # logger.debug(f'{vt_symbol}: order pirce: {order.price}, price: {price}')
            if abs(order.price - price) < 0.1:
                continue
            self.cancel_order(order)


    def set_task(self, target_pos: Series):
        self.target_pos = target_pos
        current_pos = self.position_management.to_series()
        self.change_pos = self.target_pos.sub(current_pos, fill_value=0)

        if datetime.now().hour > 16:
            to_delay = []
            for sym in self.change_pos.index:
                if not lq.future_contract_is_night_trading(sym):
                    to_delay.append(sym)
            self.logger.info(f'night trade, delay {to_delay}')
            self.change_pos.drop(to_delay, inplace=True)

        self.logger.info(f'ori_change_pos:{self.change_pos}')

        is_finished = []
        for sym in self.change_pos.index:
            if self.is_finished(sym):
                is_finished.append(sym)

        self.logger.info(f'remove finished {is_finished}')
        self.change_pos.drop(is_finished, inplace=True)

        self.logger.info(f'drop change_pos :{self.change_pos}')

        self.subscribe_symbols(self.change_pos.index)
        self.finished = Series(False, index=self.change_pos.index)
        self.status = FuckerStatus.SET_TASK

    def start(self, at: datetime = None):
        if self.change_pos is None or len(self.change_pos) == 0:
            self.logger.info('nothing changed. exit.')
            self._stop()
        else:
            if at is not None:
                time.sleep((at - datetime.now()).seconds)
            self.status = FuckerStatus.RUNNING
